﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;

namespace YArchitech.Revit.Electric.Common
{
	public class RevitUtils
	{
		public static List<GeometryObject> GetGeometry(Element elem, Options options)
		{
			return new YJKElement(elem).GetGeometry(options);
		}

		public static List<Connector> GetWireConnectors(Wire wire)
		{
			List<Connector> list = new List<Connector>();
			ConnectorSetIterator connectorSetIterator = wire.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
				if (connector.Domain == (Autodesk.Revit.DB.Domain)2)
				{
					list.Add(connector);
				}
			}
			return list;
		}

		public static List<Element> GetEquipmentByConnectors(List<Connector> connectorList)
		{
			List<Element> list = new List<Element>();
			foreach (Connector connector in connectorList)
			{
				ConnectorSet allRefs = connector.AllRefs;
				if (allRefs.Size > 0)
				{
					foreach (object obj in allRefs)
					{
						Element owner = ((Connector)obj).Owner;
						if (owner is FamilyInstance)
						{
							list.Add(owner);
						}
					}
				}
			}
			return list;
		}

		public static void GetWireConnectedEquipment(Wire wire, out Element startElement, out Element endElement)
		{
			startElement = null;
			endElement = null;
			List<Connector> wireConnectors = RevitUtils.GetWireConnectors(wire);
			if (wireConnectors.Count == 0)
			{
				return;
			}
			List<Element> equipmentByConnectors = RevitUtils.GetEquipmentByConnectors(wireConnectors);
			if (equipmentByConnectors.Count == 0)
			{
				return;
			}
			if (equipmentByConnectors.Count == 1)
			{
				XYZ point = (equipmentByConnectors[0].Location as LocationPoint).Point;
				using (List<Connector>.Enumerator enumerator = wireConnectors.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (enumerator.Current.Origin.IsAlmostEqualTo(point))
						{
							startElement = equipmentByConnectors[0];
						}
						else
						{
							endElement = equipmentByConnectors[0];
						}
					}
				}
			}
			if (equipmentByConnectors.Count == 2)
			{
				XYZ hyendPoint = (wire.Location as LocationCurve).Curve.GetEndPoint(0);
				XYZ point2 = (equipmentByConnectors[0].Location as LocationPoint).Point;
				XYZ point3 = (equipmentByConnectors[1].Location as LocationPoint).Point;
				if (point2.DistanceTo(hyendPoint) < point3.DistanceTo(hyendPoint))
				{
					startElement = equipmentByConnectors[0];
					endElement = equipmentByConnectors[1];
					return;
				}
				startElement = equipmentByConnectors[1];
				endElement = equipmentByConnectors[0];
			}
		}

		public static Connector GetDeviceConnector(Element element)
		{
			Connector result = null;
			ConnectorSetIterator connectorSetIterator = (element as FamilyInstance).MEPModel.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
				if (connector.Domain == (Autodesk.Revit.DB.Domain)2)
				{
					result = connector;
					break;
				}
			}
			return result;
		}

		public static List<Connector> GetConduitConnectors(Conduit conduit)
		{
			List<Connector> list = new List<Connector>();
			ConnectorSetIterator connectorSetIterator = conduit.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector item = obj as Connector;
				list.Add(item);
			}
			return list;
		}

		public static List<Connector> GetConduitFittingConnectors(Element element)
		{
			List<Connector> list = new List<Connector>();
			FamilyInstance familyInstance = element as FamilyInstance;
			if (familyInstance == null)
			{
				return list;
			}
			ConnectorSetIterator connectorSetIterator = familyInstance.MEPModel.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector item = obj as Connector;
				list.Add(item);
			}
			return list;
		}

		public static List<Connector> GetCableTrayConnectors(CableTrayConduitBase cableTray)
		{
			List<Connector> list = new List<Connector>();
			ConnectorSetIterator connectorSetIterator = cableTray.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector item = obj as Connector;
				if (!list.Contains(item))
				{
					list.Add(item);
				}
			}
			return list;
		}

		public static List<Connector> GetCableTrayConduitConnector(FamilyInstance element)
		{
			List<Connector> list = new List<Connector>();
			ConnectorSetIterator connectorSetIterator = element.MEPModel.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
                if ((int)connector.Domain == 4 || connector.Domain == (Autodesk.Revit.DB.Domain)2)
				{
					list.Add(connector);
				}
			}
			return list;
		}
	}
}
